﻿using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using System;
using System.Threading;
using System.Threading.Tasks;
using YanShu.Utils;
using YanShu.Handler;
using System.Configuration;
using System.Resources;
using System.Reflection;
using System.Windows.Forms;
using System.IO;

namespace YanShu
{
    public class Client
    {
        #region Instance
        readonly private static Client client = new Client();

        readonly private static int MAX_FRAME_LENGTH = 1024 * 1024;

        readonly private static int LENGTH_FIELD_OFFSET = 0;

        readonly private static int LENGTH_FIELD_LENGTH = 4;

        readonly private static int INITIAL_BYTES_TO_STRIP = 0;

        readonly private static int LENGTH_ADJUSTMENT = 0;

        public static Client Instance => client;

        public IChannel clientChannel;

        //连接到远程服务
        Bootstrap bootstrap;

        MultithreadEventLoopGroup group;
        //连接到本地服务
        Bootstrap realServerBootstrap;


        private Client()
        {
            group = new MultithreadEventLoopGroup();
            realServerBootstrap = new Bootstrap();
            realServerBootstrap.Group(group)
                    .Channel<TcpSocketChannel>()
                    .Option(ChannelOption.TcpNodelay, true)
                    .Handler(new ActionChannelInitializer<ISocketChannel>(channel =>
                    {
                        IChannelPipeline pipeline = channel.Pipeline;
                        pipeline.AddLast(new RealServerChannelHandler());

                    }));

            bootstrap = new Bootstrap();
            bootstrap.Group(group)
                    .Channel<TcpSocketChannel>()
                    .Option(ChannelOption.TcpNodelay, true)
                    .Handler(new ActionChannelInitializer<ISocketChannel>(channel =>
                    {
                        IChannelPipeline pipeline = channel.Pipeline;
                        pipeline.AddLast("messageEnCoder", new ProxyMessageEncoder());
                        pipeline.AddLast("meessageDeCoder", new ProxyMessageDecoder(MAX_FRAME_LENGTH, LENGTH_FIELD_OFFSET, LENGTH_FIELD_LENGTH, LENGTH_ADJUSTMENT, INITIAL_BYTES_TO_STRIP));
                        pipeline.AddLast("idleStateHandle", new ProxyIdleCheckHandler(ProxyIdleCheckHandler.READ_IDLE_TIME, ProxyIdleCheckHandler.WRITE_IDLE_TIME - 10, 0));
                        pipeline.AddLast("NettyClient", new ClientChannelHandler(realServerBootstrap, bootstrap, this));
                    }));


        }
        #endregion

        public void Start()
        {
            Task.Run(() => ConnectProxyServerAsync());
        }

        private async Task ConnectProxyServerAsync()
        {
            try
            {
                clientChannel = await bootstrap.ConnectAsync(Constants.INET_HOST, Constants.INET_PORT);
                //保存信道
                ClientChannelMannager.SetCmdChannel(clientChannel);
                ClientChannelHandler.Instance.TokenAuthToServer();
            }
            catch (Exception e)
            {
                String str = e.ToString();
                ReConnectServer();
            }
        }

        //断线重连
        private void ReConnectServer()
        {
            try
            {
                Thread.Sleep(3000);
                Start();
            }
            catch (Exception e)
            {
                e.ToString();
            }
        }


        public void ChannelInactive(IChannelHandlerContext ctx)
        {
            ReConnectServer();
        }
    }
}
